Package org.python.pydev.editor.actions

Source Code of org.python.pydev.editor.actions.PyScopeSelection

/**
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Eclipse Public License (EPL).
* Please see the license.txt included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package org.python.pydev.editor.actions;

import java.util.Map;

import org.eclipse.jface.action.IAction;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension4;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.ui.texteditor.ITextEditor;
import org.python.pydev.core.docutils.PySelection;
import org.python.pydev.core.docutils.PythonPairMatcher;
import org.python.pydev.core.docutils.StringUtils;
import org.python.pydev.core.log.Log;
import org.python.pydev.core.structure.FastStack;
import org.python.pydev.editor.PyEdit;
import org.python.pydev.parser.fastparser.ScopesParser;
import org.python.pydev.parser.fastparser.ScopesParser.Scopes;

import com.aptana.shared_core.structure.Tuple;

/**
* @author fabioz
*
*/
public class PyScopeSelection extends PyAction {

    public static final String SELECTION_SCOPE_CACHE = "_SELECTION_SCOPE_CACHE_";

    public void run(IAction action) {
        try {
            ITextEditor textEditor = getTextEditor();
            IDocument doc = textEditor.getDocumentProvider().getDocument(textEditor.getEditorInput());
            ITextSelection selection = (ITextSelection) textEditor.getSelectionProvider().getSelection();

            perform(doc, selection);
        } catch (Exception e) {
            Log.log(e);
        }
    }

    public void perform(IDocument doc, ITextSelection selection) {
        PyEdit pyEdit = getPyEdit();
        FastStack<IRegion> cache = getCache(pyEdit);
        Region initialRegion = new Region(selection.getOffset(), selection.getLength());
        if (cache.size() > 0) {
            IRegion peek = cache.peek();
            if (!peek.equals(initialRegion)) {
                cache.clear();
            }
        }
        if (cache.size() == 0) {
            cache.push(initialRegion);
        }
        ITextSelection newSelection = getNewSelection(doc, selection);
        if (initialRegion.equals(new Region(newSelection.getOffset(), newSelection.getLength()))) {
            return;
        }

        pyEdit.setSelection(newSelection.getOffset(), newSelection.getLength());
        cache.push(new Region(newSelection.getOffset(), newSelection.getLength()));
    }

    public ITextSelection getNewSelection(IDocument doc, ITextSelection selection) {
        try {
            PySelection ps = new PySelection(doc, selection);
            String selectedText = ps.getSelectedText();
            if (selectedText.length() == 0) {
                //Select the current word
                Tuple<String, Integer> currToken = ps.getCurrToken();
                if (currToken.o1.length() > 0) {
                    return new TextSelection(currToken.o2, currToken.o1.length());
                } else {
                    char c = '\0';
                    try {
                        c = ps.getCharAtCurrentOffset();
                    } catch (BadLocationException e) {
                        //Ignore (end of document is selected).
                    }
                    if (StringUtils.isClosingPeer(c)) {
                        PythonPairMatcher pairMatcher = new PythonPairMatcher();
                        int openingOffset = pairMatcher.searchForOpeningPeer(ps.getAbsoluteCursorOffset(),
                                StringUtils.getPeer(c), c, doc);
                        if (openingOffset >= 0) {
                            return new TextSelection(openingOffset, ps.getAbsoluteCursorOffset() - openingOffset + 1);
                        }
                    }
                }
            } else {
                //There's already some text selected
                boolean tryMatchWithQualifier = true;
                boolean hasDotSelected = false; //value only valid if tryMatchWithQualifier == true!
                for (int i = 0; i < selectedText.length(); i++) {
                    char c = selectedText.charAt(i);
                    if (c == '.') {
                        hasDotSelected = true;
                        continue;
                    }
                    if (!Character.isJavaIdentifierPart(c)) {
                        tryMatchWithQualifier = false;
                        break;
                    }
                }
                if (tryMatchWithQualifier) {
                    Tuple<String, Integer> currToken = ps.getCurrToken();
                    if (!hasDotSelected && !currToken.o1.equals(selectedText)) {
                        return new TextSelection(currToken.o2, currToken.o1.length());
                    } else {
                        //The selected text is not equal to the current token, let's see if we have to select a full dotted word
                        Tuple<String, Integer> currDottedToken = ps.getCurrDottedStatement();
                        if (!currDottedToken.o1.equals(selectedText)) {
                            return new TextSelection(currDottedToken.o2, currDottedToken.o1.length());
                        }
                    }
                }
            }
            Scopes scopes = ScopesParser.createScopes(doc);
            //            System.out.println(scopes.debugString(doc));
            IRegion scope = scopes.getScopeForSelection(selection.getOffset(), selection.getLength());
            if (scope != null) {
                return new TextSelection(scope.getOffset(), scope.getLength());
            }

        } catch (BadLocationException e) {
            Log.log(e);
        }

        return selection;
    }

    private static String getCurrentSelectionCacheKey(PyEdit pyEdit) {
        IDocument doc = pyEdit.getDocument();

        int length = doc.getLength();
        String key = Integer.toString(length);
        if (doc instanceof IDocumentExtension4) {
            IDocumentExtension4 document = (IDocumentExtension4) doc;
            long modificationStamp = document.getModificationStamp();
            key += " - " + modificationStamp;
        }
        return key;
    }

    @SuppressWarnings("unchecked")
    public static FastStack<IRegion> getCache(PyEdit pyEdit) {
        Map<String, Object> cache = pyEdit.getCache();
        String key = getCurrentSelectionCacheKey(pyEdit);
        try {
            Tuple<String, FastStack<IRegion>> object = (Tuple<String, FastStack<IRegion>>) cache
                    .get(PyScopeSelection.SELECTION_SCOPE_CACHE);

            if (object != null) {
                if (key.equals(object.o1)) {
                    return object.o2;
                }
            }
        } catch (Exception e) {
            Log.log(e);
        }

        FastStack<IRegion> stack = new FastStack<IRegion>(20);
        cache.put(PyScopeSelection.SELECTION_SCOPE_CACHE, new Tuple<String, FastStack<IRegion>>(key, stack));
        return stack;
    }

}
TOP

Related Classes of org.python.pydev.editor.actions.PyScopeSelection

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.